﻿using System;
using System.Collections.Generic;
using Algoritmia.Utils;
using Lists = Algoritmia.DataStructures.Lists;

namespace Algoritmia.Problems.Geometry.Brownian
{
    public class BrownianMotionPointsGenerator1
    {
        private readonly Func<Lists.IList<Point2D>> _createList;
        private readonly IRandomProvider _random;
        
        public BrownianMotionPointsGenerator1(Func<Lists.IList<Point2D>> createList = null,
                                              Func<IRandomProvider> createRandomGenerator = null)
        {
            _createList = createList ?? (() => AlgoritmiaFactory.Lists<Point2D>.Default);
            createRandomGenerator = createRandomGenerator ?? (() => new RandomGaussian());
            _random = createRandomGenerator();
        }
      
        public IEnumerable<Point2D> Points(Point2D a, Point2D b, double r)
        {
            var points = _createList();
            points.Add(a);
            Action<Point2D, Point2D, double> f = null;
            f = (c, d, v) =>
                    {
                        if (d.X - c.X <= 1.0)
                            return;
                        else
                        {
                            double delta = _random.NextGaussian(0.0, Math.Sqrt(r)); 
                            var pt = new Point2D((c.X + d.X)/2.0, (c.Y + d.Y)/2.0 + delta);
                            f(c, pt, r/2.0);
                            points.Add(pt);
                            f(pt,d, r/2.0);
                        }
                    };
            f(a, b, r);
            points.Add(b);
            return points;
        }
    }
}
